package kaist.sep521.lego.circlebicycle;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;

public class RunActivity extends FragmentActivity implements
OnMapClickListener, OnMapLongClickListener, LocationListener,
android.location.LocationListener {
	String Tag = "LEGO";
	private GoogleMap mMap = null;
	private LocationManager locationManager;
	private String provider = null;
	List<LatLng> pathList;
	List<Polyline> polylines = new ArrayList<Polyline>();
	public ArrayList<User> memberList = new ArrayList<User>();

	public static String locationUrl = "http://14.63.196.253/~lego/location_update.php";
	public static String voicesendUrl = "http://14.63.196.253/~lego/voicefile_save.php?group=";

	private MediaRecorder recorder = null;
	private ProgressbarTask pTask = null;
	private ProgressBar progressBar = null;
	private int pValue = 0;

	private ImageButton startButton;
	private ImageButton recordVoiceMsg;

	boolean routeRecording = false;
	boolean duringRecordMsg = false;
	long desiredInterval = 5000; // min time
	float desiredDistance = 5; // min distance and condition

	private ArrayList<Bitmap> travelStatusList = new ArrayList<Bitmap>();
	private Bitmap restStatus;
	private Bitmap repairStatus;
	private Bitmap destination;

	private long currentTime;
	private Boolean runUiThead = true;
	PollingThread pollThread = new PollingThread(RunActivity.this);
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		BitmapFactory.Options bitmapOption = new BitmapFactory.Options();
		bitmapOption.inSampleSize = 1;
		bitmapOption.inPurgeable = true;
		bitmapOption.inDither = true;

		travelStatusList.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.cycle1, bitmapOption));
		travelStatusList.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.cycle2, bitmapOption));
		travelStatusList.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.cycle3, bitmapOption));
		travelStatusList.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.cycle4, bitmapOption));
		travelStatusList.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.cycle5, bitmapOption));
		travelStatusList.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.cycle6, bitmapOption));

		restStatus = BitmapFactory.decodeResource(getResources(),
				R.drawable.rest, bitmapOption);
		repairStatus = BitmapFactory.decodeResource(getResources(),
				R.drawable.repair, bitmapOption);
		destination = BitmapFactory.decodeResource(getResources(),
				R.drawable.destination, bitmapOption);

		PollingThread.setRunningState(true);
		pollThread.start();

		setContentView(R.layout.activity_run);

		GooglePlayServicesUtil.isGooglePlayServicesAvailable(RunActivity.this);

		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		pathList = new ArrayList<LatLng>();
		Criteria criteria = null;// = new Criteria();

		if (criteria == null) {
			criteria = new Criteria();
			criteria.setAccuracy(Criteria.ACCURACY_FINE);
			criteria.setAltitudeRequired(false);
			criteria.setBearingRequired(false);
			criteria.setSpeedRequired(true);
		}

		provider = locationManager.getBestProvider(criteria, true);

		if (provider == null) {
			new AlertDialog.Builder(RunActivity.this)
			.setTitle("GPS share OK")
			.setNeutralButton("Move",
					new DialogInterface.OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog,
						int which) {
					startActivityForResult(
							new Intent(
									android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS),
									0);
				}
			})
			.setOnCancelListener(
					new DialogInterface.OnCancelListener() {

						@Override
						public void onCancel(DialogInterface dialog) {
							finish();
						}
					})

					.show();
		} else {
			locationManager.requestLocationUpdates(provider, desiredInterval,
					desiredDistance, RunActivity.this);
			setUpMapIfNeeded();
		}

		StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
		.detectNetwork() // or .detectAll() for all detectable problems
		.penaltyDialog() // show a dialog
		.permitNetwork() // permit Network access
		.build());

		if(MainActivity.testModeFlag == false)
			location_update(MainActivity.myInfo);

		final ImageButton voiceMSG = (ImageButton) findViewById(R.id.run_recordVoice);

		// Set up the user interaction to manually show or hide the system UI.
		voiceMSG.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				// move to run window
				showVoiceMSGDialog();
			}
		});

		ImageButton drivingStatusChange = (ImageButton) findViewById(R.id.drivingStatus);
		// Set up the user interaction to manually show or hide the system UI.
		drivingStatusChange.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				// move to run window
				showDrivingStatusDialog();
			}
		});

		startButton = (ImageButton) findViewById(R.id.run_startButton);
		startButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if (routeRecording) {
					stopRouteRecording();
				} else {
					startRouteRecording();
				}
			}
		});
	}

	@Override
	protected void onResume() {
		super.onResume();
		setUpMapIfNeeded();
	}

	@Override
	protected void onPause() {
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		pollThread.interrupt();
		PollingThread.setRunningState(false);
		runUiThead = false;
		unregisterLocationListener();
		removeProximityAlert();
		super.onDestroy();
	}

	private void setUpMapIfNeeded() {
		if (mMap == null) {
			// Try to obtain the map from the SupportMapFragment.
			mMap = ((SupportMapFragment) getSupportFragmentManager()
					.findFragmentById(R.id.run_mapview)).getMap();
			// Check if we were successful in obtaining the map.
			if (mMap != null) {
				setUpMap();
			}
		}
	}

	private void setUpMap() {
		LatLng myloction = new LatLng(37.0, 127.0);

		if(MainActivity.testModeFlag == false){
			mMap.setMyLocationEnabled(true);
			mMap.getMyLocation();
		}else{
			mMap.setMyLocationEnabled(false);
		}


		mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
		mMap.setOnMapLongClickListener(this);
		mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(myloction, 17));

		pathList.clear();
	}

	public void parseUserList(String group) {
		String userID= MainActivity.myInfo.getID();
		try {
			String xml = "http://14.63.196.253/~lego/update_data.php?user="+userID+"&group="
					+ group;
			URL url = new URL(xml);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				InputStream is = conn.getInputStream();

				SAXParserFactory spf = SAXParserFactory.newInstance();
				SAXParser sp = spf.newSAXParser();
				XMLReader xr = sp.getXMLReader();
				ParserHandler pHandler = new ParserHandler();
				xr.setContentHandler(pHandler);
				xr.parse(new InputSource(is));

				if (memberList != null)
					memberList.clear();
				memberList = pHandler.getParsedData();
			} else {
				Toast.makeText(this, "Server connection error!!", Toast.LENGTH_SHORT).show();
			}
			conn.disconnect();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void showVoiceMSGDialog() {
		// dialog
		final Dialog dialog = new Dialog(this);
		dialog.setContentView(R.layout.dialog_voicemsg);
		dialog.setTitle("Record voice message !!!");

		progressBar = (ProgressBar) dialog
				.findViewById(R.id.voicemsg_progressBar);
		recordVoiceMsg = (ImageButton) dialog.findViewById(R.id.voicemsg_start);
		ImageButton send = (ImageButton) dialog
				.findViewById(R.id.voicemsg_send);

		// auto start
		recordVoiceMsg();

		// if button is clicked, close the custom dialog
		recordVoiceMsg.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (duringRecordMsg) {
					stopVoiceMsg();
				} else {
					recordVoiceMsg();
				}

			}
		});

		send.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// stop the voice MSG
				pTask.cancel(true);
				stopRecord();

				String filePath = "/sdcard/circlebicycle/CBC_recorded.mp4";
				sendFile(voicesendUrl + MainActivity.myInfo.getGroup()
						+ "&user=" + MainActivity.myInfo.getID(), filePath);

				dialog.dismiss();
			}
		});

		dialog.show();
	}

	private void recordVoiceMsg() {
		duringRecordMsg = true;
		recordVoiceMsg.setImageResource(R.drawable.av_stop);

		// progress start
		pTask = new ProgressbarTask();
		pTask.execute(100);

		// record the voice MSG
		startRecord();
	}

	private void stopVoiceMsg() {
		duringRecordMsg = false;
		recordVoiceMsg.setImageResource(R.drawable.record);

		// progress stop
		pTask.cancel(true);

		// stop the voice MSG
		stopRecord();
	}

	class ProgressbarTask extends AsyncTask<Integer, Integer, Integer> {
		protected void onPreExecute() {
			pValue = 0;
			progressBar.setProgress(pValue);
		}

		protected Integer doInBackground(Integer... values) {
			while (isCancelled() == false) {
				pValue++;
				if (pValue >= 100) {
					break;
				} else {
					publishProgress(pValue);
				}

				try {
					Thread.sleep(100);
				} catch (InterruptedException ex) {
				}
			}

			return pValue;
		}

		protected void onProgressUpdate(Integer... values) {
			progressBar.setProgress(values[0].intValue());
		}

		protected void onPostExecute(Integer result) {
			// progressBar.setProgress(0);
		}

		protected void onCancelled() {
			// progressBar.setProgress(0);
		}
	}

	private void startRecord() {
		String filePath = "/sdcard/circlebicycle/CBC_recorded.mp4";
		File dir = new File("/sdcard/circlebicycle");
		if (!dir.isDirectory()) {
			dir.mkdirs();
		}

		if (recorder == null) {
			recorder = new MediaRecorder();
			recorder.reset();
		} else {
			recorder.reset();
		}

		try {
			recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
			recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
			recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
			recorder.setOutputFile(filePath);
			recorder.prepare();
			recorder.start();
		} catch (IllegalStateException e) {
			Toast.makeText(this, "IllegalStateException", Toast.LENGTH_SHORT)
			.show();
		} catch (IOException e) {
			Toast.makeText(this, "IOException", Toast.LENGTH_SHORT).show();

		}
	}

	private void stopRecord() {
		if (recorder == null)
			return;

		try {
			recorder.stop();
		} catch (Exception e) {
			Toast.makeText(this, "Exception", Toast.LENGTH_SHORT).show();
		} finally {
			recorder.release();
			recorder = null;
		}
	}

	private void playVoiceMessage(String filePath) {
		MediaPlayer player = new MediaPlayer();
		try {
			player.setDataSource(filePath);
			player.prepare();
			player.start();
		} catch (IOException ioe) {
			Toast.makeText(this, "Play fail", Toast.LENGTH_SHORT).show();
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {

		super.onActivityResult(requestCode, resultCode, data);

		switch (requestCode) {
		case 0:
			locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
			Criteria criteria = new Criteria();
			provider = locationManager.getBestProvider(criteria, true);

			if (provider == null) {
				finish();
			} else {
				locationManager.requestLocationUpdates(provider,
						desiredInterval, desiredDistance, RunActivity.this);

				setUpMapIfNeeded();
			}
			break;
		}
	}

	Marker myMarker = null;
	Polyline polyLine;
	List<LatLng> points;

	@Override
	public void onLocationChanged(Location location) {
		double lat = location.getLatitude();
		double lng = location.getLongitude();

		if(MainActivity.testModeFlag == false){
			MainActivity.myInfo.setLatitude(lat);
			MainActivity.myInfo.setLongitude(lng);
			location_update(MainActivity.myInfo);
			drawMyinfo();
			drawDestinationDistance();
		}
	}

	public void drawDestinationDistance()
	{
		double destiLat = 0;
		double destiLng = 0;

		if( !memberList.isEmpty() )
		{
			for (int i = 0; i < memberList.size(); i++) {
				String tmpID = memberList.get(i).getID();
				if (tmpID != null && tmpID.equals("destination")) {
					destiLat = memberList.get(i).getLatitude();
					destiLng = memberList.get(i).getLongitude();
				}
			}

			calcDistance(destiLat, destiLng);
		}		
	}

	private void drawMyinfo() {
		LatLng myLocation = new LatLng(MainActivity.myInfo.getLatitude(),
				MainActivity.myInfo.getLongitude());

		int status = MainActivity.myInfo.getStatus();

		Bitmap marker_bmp;

		if (status == 0) {
			marker_bmp = travelStatusList.get(travelStatusList.size()-1);
		} else if (status == 1) {
			marker_bmp = restStatus;
		} else if (status == 2) {
			marker_bmp = repairStatus;
		} else
			marker_bmp = destination;

		mMap.animateCamera(CameraUpdateFactory.newLatLng(myLocation));

		if (myMarker != null)
			myMarker.remove();

		myMarker = mMap.addMarker(new MarkerOptions().position(myLocation)
				.title(MainActivity.myInfo.getNickname())
				.snippet(MainActivity.myInfo.getID())
				.icon(BitmapDescriptorFactory.fromBitmap(marker_bmp)));

		if (routeRecording) {
			pathList.add(myLocation);
			PolylineOptions options = new PolylineOptions();
			options.addAll(pathList);
			options.geodesic(true);
			polylines.add(mMap.addPolyline(options.color(Color.GRAY).width(3)));

		}
	}

	public void calcMileage() {
		double avgSpeed = 0;
		int avgSpeedMH = 0;
		int elapsedTime = 0;
		int sumOfdistance = 0;
		float[] distance = new float[3];

		for (int i = 1; i < pathList.size(); i++) {
			Location.distanceBetween(pathList.get(i - 1).latitude,
					pathList.get(i - 1).longitude, pathList.get(i).latitude,
					pathList.get(i).longitude, distance);

			sumOfdistance += distance[0];
		}

		elapsedTime = (int) ((System.currentTimeMillis() - currentTime) / 1000);// second
		if (elapsedTime > 0)
			avgSpeed = sumOfdistance / elapsedTime; // meter/s
		avgSpeedMH = (int) (avgSpeed * 3600); // meter/h

		updateResult(sumOfdistance, avgSpeedMH);
	}

	@Override
	public void onProviderDisabled(String provider) {
	}

	@Override
	public void onProviderEnabled(String provider) {
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
	}

	@Override
	public void onMapClick(LatLng point) {
		mMap.animateCamera(CameraUpdateFactory.newLatLng(point));
	}

	@Override
	public void onMapLongClick(LatLng point) {
		showDestinationDialog(point);
	}

	private void showDestinationDialog(final LatLng point) {
		// dialog
		final Dialog dialog = new Dialog(this);
		dialog.setContentView(R.layout.dialog_destination);
		dialog.setTitle("config destination !!");

		Button add = (Button) dialog.findViewById(R.id.add);
		Button delete = (Button) dialog.findViewById(R.id.delete);
		Button cancle = (Button) dialog.findViewById(R.id.cancle);

		// if button is clicked, close the custom dialog
		add.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				addDestination(point);
				dialog.dismiss();
			}
		});

		delete.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				deleteDestination(point);
				dialog.dismiss();
			}
		});

		cancle.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.dismiss();
			}
		});

		dialog.show();
	}

	private void addDestination(LatLng point) {
		User destination = new User();
		destination.setID("destination");
		destination.setLatitude(point.latitude);
		destination.setLongitude(point.longitude);
		destination.setStatus(3);
		destination.setGroup(MainActivity.myInfo.getGroup());
		destination_update(destination);
		
		calcDistance(point.latitude, point.longitude);
		addProximityAlert(point.latitude, point.longitude, 100f, -1);	//100f[m]
	}

	private void deleteDestination(LatLng point) {
		User destination = new User();
		destination.setID("destination");
		destination.setLatitude(point.latitude);
		destination.setLongitude(point.longitude);
		destination.setStatus(99);
		destination.setGroup(MainActivity.myInfo.getGroup());
		destination_update(destination);

		removeProximityAlert();
	}

	private void showDrivingStatusDialog() {
		final CharSequence[] UserStatusitems = { "travel", "rest", "repair" };

		new AlertDialog.Builder(RunActivity.this)
		.setTitle("Setting driving status!")
		.setSingleChoiceItems(UserStatusitems,
				MainActivity.myInfo.getStatus(),
				new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog,
					int whichButton) {
			}
		})
		.setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {
				int selectedPosition = ((AlertDialog) dialog)
						.getListView().getCheckedItemPosition();
				MainActivity.myInfo.setStatus(selectedPosition);
				drawMyinfo();
				location_update(MainActivity.myInfo);
			}
		})
		.setNegativeButton("Cancle",
				new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog,
					int whichButton) {
			}
		})
		.show();
	}

	private void startRouteRecording() {
		if (routeRecording) {
			return;
		}

		registerLocationListener();
		routeRecording = true;

		startButton.setImageResource(R.drawable.av_stop);
		currentTime = System.currentTimeMillis();

		playRawAudio(R.raw.start);		
	}

	private void playRawAudio(int resid) {
		MediaPlayer player;
		player = MediaPlayer.create(RunActivity.this, resid);
		player.start();
	}	

	private void stopRouteRecording() {
		routeRecording = false;

		unregisterLocationListener();
		calcMileage();
		pathList.clear();

		for (Polyline line : polylines) {
			line.remove();
		}

		polylines.clear();
		startButton.setImageResource(R.drawable.av_play);
	}

	private void registerLocationListener() {
		if (locationManager == null) {
			return;
		}

		try {
			locationManager.requestLocationUpdates(provider,// LocationManager.GPS_PROVIDER,
					desiredInterval, desiredDistance, RunActivity.this);
		} catch (RuntimeException e) {
			Log.e("ashton",
					"Could not register location listener : " + e.getMessage(),
					e);
		}
	}

	private void unregisterLocationListener() {
		if (locationManager == null) {
			return;
		}

		locationManager.removeUpdates(this);
	}

	static ArrayList<Marker> markerList = new ArrayList<Marker>();

	public void runOnUiThread() {
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				if(runUiThead)
				{
					parseUserList(MainActivity.myInfo.getGroup());
					drawMember(memberList);
					if(MainActivity.testModeFlag == true)
					{
						drawMyinfo();
						drawDestinationDistance();
					}
				}
			}
		});
	}

	public synchronized void drawMember(ArrayList<User> memberList) {

		int status = 0;
		String tmpID = null;
		String tmpNickname = null;
		Geocoder gc = null;
		List<Address> addressList = null;
		Bitmap marker_bmp;

		if( memberList.isEmpty() )
			return;

		for (int i = 0; i < markerList.size(); i++) {
			markerList.get(i).remove();
		}

		for (int i = 0; i < memberList.size(); i++) {
			if (memberList.get(i).getShareLocation() == false)
				continue;

			status = memberList.get(i).getStatus();
			if (status == 0) {
				if(i >= travelStatusList.size())	i=0;
				marker_bmp = travelStatusList.get(i);
			} else if (status == 1) {
				marker_bmp = restStatus;
			} else if (status == 2) {
				marker_bmp = repairStatus;
			} else
				marker_bmp = destination;

			tmpID = memberList.get(i).getID();
			tmpNickname = memberList.get(i).getNickname();

			if (tmpID!=null && tmpID.equals("destination")) {
				gc = new Geocoder(this, Locale.KOREAN);
				try {
					addressList = gc.getFromLocation(memberList.get(i).getLatitude(), memberList.get(i).getLongitude(), 1);
				} catch (IOException e) {
					e.printStackTrace();
				}

				if(addressList!=null && !addressList.isEmpty())
				{
					tmpNickname = addressList.get(0).getAddressLine(0);
					addressList.removeAll(addressList);
				}
				marker_bmp = destination;
			}

			LatLng myloction = new LatLng(memberList.get(i).getLatitude(),
					memberList.get(i).getLongitude());

			markerList.add(mMap.addMarker(new MarkerOptions()
			.position(myloction)
			.title(tmpNickname)
			.snippet(tmpID)
			.icon(BitmapDescriptorFactory.fromBitmap(marker_bmp))));
		}
	}



	public void checkVoiceMSG() {
		boolean voiceTag = false;
		String username = MainActivity.myInfo.getID();
		String filePath = "/sdcard/circlebicycle/CBC_recorded.mp4";
		String voiceUrl = "http://14.63.196.253/~lego/"
				+ MainActivity.myInfo.getGroup() + ".mp4";

		voiceTag = checkvoiceTag(username);

		// Then, reset the Voice Tag on the server
		if (voiceTag == true) {
			// Call File load from server
			downloadFile(voiceUrl);

			// And play the Voice Message.
			playVoiceMessage(filePath);

			// Clear the Voice Tag on the server.
			try {
				String xml = "http://14.63.196.253/~lego/voiceTagClear.php?user="
						+ username;

				URL url = new URL(xml);
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();

				if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
					Log.e(Tag, "parseUserList > ClearVoiceTag.HTTP_OK");

				} else {
					Toast.makeText(this, "Server connection error!!",
							Toast.LENGTH_SHORT).show();
				}
				conn.disconnect();

			} catch (Exception e) {
				e.printStackTrace();
			}

		} else {
			Log.e(Tag, "parseUserList > NO_VOICE_MESSAGE");
		}
	}

	private boolean checkvoiceTag(String username) {
		String checkTagUrl = "http://14.63.196.253/~lego/voiceTagCheck.php";

		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(checkTagUrl);
		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("user", username));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			// Execute HTTP Post Request
			HttpResponse response = httpclient.execute(httppost);
			String str = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);

			if (str.toString().equalsIgnoreCase("true")) {
				return (true);
			} else {
				return (false);
			}

		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return (false);
	}

	public void calcDistance(double destinationlat, double destinationlng) {
		float[] distance = new float[3];

		LatLng myLoction = new LatLng(MainActivity.myInfo.getLatitude(),
				MainActivity.myInfo.getLongitude());

		TextView destinationDistance = (TextView) findViewById(R.id.destinationDistance);

		Location.distanceBetween(myLoction.latitude, myLoction.longitude,
				destinationlat, destinationlng, distance);

		String d = "Dest : " + Float.toString((float)Math.round((distance[0]/1000)*100)/100) + " Km";
		destinationDistance.setText(d);
	}

	private String sendFile(String urlString, String existingFileName) {

		HttpURLConnection conn = null;
		DataOutputStream dos = null;
		DataInputStream inStream = null;
		String lineEnd = "\r\n";
		String twoHyphens = "--";
		String boundary = "*****";
		int bytesRead, bytesAvailable, bufferSize;
		byte[] buffer;
		int maxBufferSize = 100 * 1024;

		try {
			// ------------------ CLIENT REQUEST
			FileInputStream fileInputStream = new FileInputStream(new File(
					existingFileName));
			// open a URL connection to the Servlet
			URL url = new URL(urlString);
			// Open a HTTP connection to the URL
			conn = (HttpURLConnection) url.openConnection();
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Content-Type",
					"multipart/form-data;boundary=" + boundary);
			dos = new DataOutputStream(conn.getOutputStream());
			dos.writeBytes(twoHyphens + boundary + lineEnd);
			dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
					+ existingFileName + "\"" + lineEnd);
			dos.writeBytes(lineEnd);
			// create a buffer of maximum size
			bytesAvailable = fileInputStream.available();
			bufferSize = Math.min(bytesAvailable, maxBufferSize);
			buffer = new byte[bufferSize];
			// read file and write it into form...
			bytesRead = fileInputStream.read(buffer, 0, bufferSize);

			while (bytesRead > 0) {
				dos.write(buffer, 0, bufferSize);
				bytesAvailable = fileInputStream.available();
				bufferSize = Math.min(bytesAvailable, maxBufferSize);
				bytesRead = fileInputStream.read(buffer, 0, bufferSize);

			}

			// send multipart form data necesssary after file data...
			dos.writeBytes(lineEnd);
			dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

			fileInputStream.close();
			dos.flush();
			dos.close();
		} catch (MalformedURLException ex) {
			Log.e("Debug", "error: " + ex.getMessage(), ex);
		} catch (IOException ioe) {
			Log.e("Debug", "error: " + ioe.getMessage(), ioe);
		}

		// ------------------ read the SERVER RESPONSE
		try {
			inStream = new DataInputStream(conn.getInputStream());
			String str;
			while ((str = inStream.readLine()) != null) {
				;
			}
			inStream.close();
		} catch (IOException ioex) {
			Log.e("Debug", "error: " + ioex.getMessage(), ioex);
		}
		return ("OK");
	}

	public void downloadFile(String url) {
		int read = 0;
		String path = "/sdcard/circlebicycle/CBC_recorded.mp4";
		URL down = null;
		HttpURLConnection conn = null;
		InputStream is = null;
		FileOutputStream fos = null;
		File f = null;

		try {
			down = new URL(url);
			conn = (HttpURLConnection) down.openConnection();
			f = new File(path);
			if (f.exists()) {
				f.delete();
			}
			byte[] buffer = new byte[1024];
			is = conn.getInputStream();
			fos = new FileOutputStream(f);
			while ((read = is.read(buffer)) != -1) {
				fos.write(buffer, 0, read);
			}
		} catch (MalformedURLException e) {
		} catch (IOException e) {
		} finally {
			try {
				is.close();
				fos.close();
				conn.disconnect();
			} catch (IOException e) {
			}
		}

	}

	private void updateResult(int distance, int avgSpeed) {
		String group = MainActivity.myInfo.getGroup();
		String user = MainActivity.myInfo.getID();

		if (group.equals("No Joined Circles")) {
			group = "";
		}

		String updateUrl = "http://14.63.196.253/~lego/result_update.php?user="
				+ user + "&group=" + group + "&distance=" + distance
				+ "&speed=" + avgSpeed;

		// Clear the Voice Tag on the server.
		try {

			URL url = new URL(updateUrl);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();

			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				Log.w("USER SETTING", "HTTP_SEND_OK");

			} else {
				Toast.makeText(this, "Server connection error!!",
						Toast.LENGTH_SHORT).show();
			}
			conn.disconnect();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String location_update(User userInfo) {
		String username = userInfo.getID();
		double hori = userInfo.getLatitude();
		double verti = userInfo.getLongitude();
		int status = userInfo.getStatus();

		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(locationUrl);

		try {
			// Need to update !!
			// Acquire Phone Number by using phone_API.
			String phoneNumber = "01000001234";

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("user", username));
			nameValuePairs.add(new BasicNameValuePair("hori", Double
					.toString(hori)));
			nameValuePairs.add(new BasicNameValuePair("verti", Double
					.toString(verti)));
			nameValuePairs.add(new BasicNameValuePair("status", Integer
					.toString(status)));

			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			HttpResponse response = httpclient.execute(httppost);
			String str = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);

			if (str.toString().equalsIgnoreCase("true")) {
				return ("true");
			} else {
				return (str);
			}

		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ("Network Connection Error.");
	}

	private String destination_update(User userInfo) {
		String username = userInfo.getID();
		double hori = userInfo.getLatitude();
		double verti = userInfo.getLongitude();
		int status = userInfo.getStatus();
		String group = userInfo.getGroup();

		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(locationUrl);

		try {
			// Need to update !!
			// Acquire Phone Number by using phone_API.
			String phoneNumber = "01000001234";

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("user", username));
			nameValuePairs.add(new BasicNameValuePair("hori", Double
					.toString(hori)));
			nameValuePairs.add(new BasicNameValuePair("verti", Double
					.toString(verti)));
			nameValuePairs.add(new BasicNameValuePair("status", Integer
					.toString(status)));
			nameValuePairs.add(new BasicNameValuePair("group", group));

			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			HttpResponse response = httpclient.execute(httppost);
			String str = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);

			if (str.toString().equalsIgnoreCase("true")) {
				return ("true");
			} else {
				return (str);
			}

		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ("OK");
	}

	/**
	 * register the proximity intent receiver
	 */
	PendingIntent proximityIntent;
	private void addProximityAlert(double latitude, double longitude, float radius, long expiration) {
		LocationReceiver locReceiver = new LocationReceiver();
		IntentFilter filter = new IntentFilter("com.androidhuman.example.Location");
		registerReceiver(locReceiver, filter);

		Intent intent = new Intent("com.androidhuman.example.Location");
		proximityIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
		locationManager.addProximityAlert(latitude, longitude, radius, expiration, proximityIntent);
	}

	private void removeProximityAlert() {
		if (proximityIntent != null) {
			locationManager.removeProximityAlert(proximityIntent);
			proximityIntent = null;
		}
	}

	public class LocationReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			boolean isEntering = intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
			if(isEntering)
			{
				playRawAudio(R.raw.near);		
			}
		}
	}
}
